package net.app.zoneland.platform.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.app.zoneland.common.core.vo.PageResult;
import net.app.zoneland.common.core.vo.Result;
import net.app.zoneland.domain.SysMenu;
import net.app.zoneland.domain.SysRoleMenu;
import net.app.zoneland.domain.SysUser;
import net.app.zoneland.platform.service.ISysMenuService;
import net.app.zoneland.platform.service.ISysRoleMenuService;
import net.app.zoneland.vo.MenuTreeVo;
import net.app.zoneland.vo.MenuVO;
import net.app.zoneland.vo.TreeSelectVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

import static java.awt.SystemColor.menu;
import static java.util.Optional.ofNullable;

@Api(tags = "菜单接口")
@RestController
@RequestMapping("/menus")
@Slf4j
@AllArgsConstructor
public class SysMenuController {

    private final static Logger logger = LoggerFactory.getLogger(SysMenuController.class);

    private final ISysMenuService iSysMenuService;

    private final ISysRoleMenuService iSysRoleMenuService;

    @ApiOperation(value = "菜单列表", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "菜单名称", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "roleId", value = "角色ID", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "mode", value = "查询模式: 1-表格数据 2-树形数据 3-菜单路由", paramType = "query", dataType = "Integer")
    })
    @Cacheable(value="menus:list")  //自动根据方法生成缓存
    @GetMapping("/")
    public Result list(@RequestParam(value="name",required=false) String name,@RequestParam(value="roleIds",required=false) List<Integer> roleIds, @RequestParam(value="mode",required=true) Integer mode) {
        LambdaQueryWrapper<SysMenu> baseQuery = new LambdaQueryWrapper<SysMenu>()
                .orderByAsc(SysMenu::getSort)
                .orderByDesc(SysMenu::getGmtModified)
                .orderByDesc(SysMenu::getGmtCreate);
        List list;
        if (1==mode) { // 表格数据
            baseQuery = baseQuery.like(StrUtil.isNotBlank(name), SysMenu::getName, name);
            list = iSysMenuService.listForTableData(baseQuery);
        } else if (2==mode) { // 树形数据
            list = iSysMenuService.listForTreeSelect(baseQuery);
            if (roleIds != null && !roleIds.isEmpty()) { // 菜单树形 + 角色权限
                Map<String, Object> map = new HashMap<>();
                map.put("menus", list);
                HashSet<Integer> set = new HashSet<>();
                roleIds.forEach(roleId ->{
                List<Integer> checkedKeys = iSysRoleMenuService.list(new LambdaQueryWrapper<SysRoleMenu>()
                      .eq(SysRoleMenu::getRoleId, roleId))
                      .stream()
                      .map(item -> item.getMenuId())
                      .collect(Collectors.toList());
                      checkedKeys.forEach(key ->{
                        set.add(key);
                      });
                });
                List<Integer> result = new ArrayList<Integer>(set);
                map.put("checkedKeys", result);
                return Result.success(map);
            }
            return Result.success(list);
        } else if (3==mode) {
            list = iSysMenuService.listForRouter();
        } else {
            list = iSysMenuService.list(baseQuery);
        }
        return Result.success(list);
    }

    @ApiOperation(value = "菜单列表", httpMethod = "GET")
    @ApiImplicitParam(name = "roleId", value = "角色ID", paramType = "query", dataType = "Integer")
    @Cacheable(value="menus:list:Index")  //自动根据方法生成缓存
    @GetMapping("/Index")
    public Result Index(@RequestParam(value="roleIds",required=false) String roleIds){
      SysMenu menus=new SysMenu();
      menus.setRoleIds(roleIds);
       List<TreeSelectVO> list = iSysMenuService.listForTreeSelectByRole(menus);
        return Result.success(list);
    }

    @ApiOperation(value = "菜单列表", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "当前页", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "limit", value = "每页显示数", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "menu", value = "菜单实体类", paramType = "body", dataType = "SysMenu")
    })
    @Cacheable(value="query:menus:list")  //自动根据方法生成缓存
    @GetMapping("/list")
    public Result list(Integer page, Integer limit, SysMenu menu){
        Page<SysMenu> objectPage = new Page<>(page, limit);
        IPage<SysMenu> list = iSysMenuService.list(objectPage, menu);
        return PageResult.success(list.getRecords(), objectPage.getTotal());
    }

    @ApiOperation(value = "菜单详情", httpMethod = "GET")
    @ApiImplicitParam(name = "id", value = "菜单id", required = true, paramType = "path", dataType = "Integer")
    @GetMapping("/{id}")
    public Result detail(@PathVariable Integer id) {
        SysMenu menu = iSysMenuService.getById(id);
        return Result.success(menu);
    }

    @ApiOperation(value = "查询所有父级", httpMethod = "GET")
    @ApiImplicitParam(name = "parentId", value = "父菜单id", required = true, paramType = "path", dataType = "Integer")
    @GetMapping("/query/{parentId}")
    public Result detailByParentId(@PathVariable Integer parentId) {
        List<SysMenu> sysMenus = iSysMenuService.queryMenus(parentId);
        return Result.success(sysMenus);
    }

    @CacheEvict(value = "menus:list,query:menus:list")//删除缓存
    @ApiOperation(value = "新增/更新菜单", httpMethod = "POST")
    @ApiImplicitParam(name = "menu", value = "实体JSON对象", required = true, paramType = "body", dataType = "SysMenu")
    @PostMapping
    public Result addOrUp(@Valid MenuTreeVo menu, BindingResult result) {

        if(result.hasErrors()){
            return Result.error(result.getFieldError().getDefaultMessage());
        }
        Result res = iSysMenuService.saveOrUp(menu);
        return res;
    }

    @ApiOperation(value = "修改菜单", httpMethod = "PUT")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "menu", value = "实体JSON对象", required = true, paramType = "body", dataType = "SysMenu")
    })
    @PostMapping(value = "/update")
    public Result update(
            @RequestBody SysMenu menu) {
        if(ofNullable(menu).isPresent() && menu.getId()!=null){
            boolean status = iSysMenuService.updateById(menu);
            return Result.status(status);
        }
        return Result.status(false);
    }

    /**
     * 批量删除
     * @param ids
     * @return
     */
    @ApiOperation(value = "删除菜单", httpMethod = "DELETE")
    @ApiImplicitParam(name = "ids[]", value = "id集合", required = true, paramType = "query", allowMultiple = true, dataType = "Integer")
    @DeleteMapping
    public Result delete(@RequestParam("ids") List<Long> ids) {
        if(!ids.isEmpty()){
            boolean status = iSysMenuService.removeByIds(ids);
            return Result.status(status);
        }
        return Result.status(false);
    }

    @ApiOperation(value = "删除【局部更新】", httpMethod = "DELETE")
    @ApiImplicitParam(name = "id", value = "菜单id", required = true, paramType = "path", dataType = "Integer")
    @PostMapping(value = "/deleteById")
    public Result deleteById(Integer id) {
        if(id!=null && !"".equals(id)){
            iSysMenuService.deleteByIds(id);
            return Result.success();
        }
        return Result.error("删除失败");
    }

    @ApiOperation(value = "根据登录账号查询菜单", httpMethod = "GET")
    @GetMapping("/menusList/{username}")
    public Result menusListByUsername(@PathVariable String username){
        if(StringUtils.isNotBlank(username)){
            List<MenuVO> menuVOS = iSysMenuService.queryMenus(username);
            return Result.success(menuVOS);
        }
        return Result.error(username+"不能为空");
    }

    @ApiOperation(value = "获取菜单分页列表", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageIndex", value = "页码", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "pageSize", value = "每页数量", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "name", value = "名称", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "visible", value = "是否禁用", paramType = "query", dataType = "Integer")
    })
    @GetMapping("/getMenuList")
    public Result<Page<SysMenu>> getMenuList(Integer pageIndex, Integer pageSize, String name, String visible){ //@RequestParam Map<String, Object> params
        LambdaQueryWrapper<SysMenu> baseQuery = new LambdaQueryWrapper<SysMenu>();
        baseQuery.like(StrUtil.isNotBlank(name), SysMenu::getName, name);
        if(visible!=null && !"".equals(visible)){
            baseQuery.eq(SysMenu::getVisible, visible);
        }
        Page<SysMenu> sysMenuPage = iSysMenuService.page(new Page<SysMenu>(pageIndex, pageSize), baseQuery);
        return Result.success(sysMenuPage);
    }


    @GetMapping("/getAuthoriList")
    public Result getAuthoriList(SysMenu menu){
        List<MenuTreeVo> menus = iSysMenuService.getMenus(menu);
        return Result.success(menus);
    }
}
